/*
 * Copyright 2010 Joshua Smith and Nelson Llewellyn
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package norse.util;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

/**
 * A list of IP Address Ranges. Automatically merges ranges on insert.
 */
public class IPv4RangeList
{

    public IPv4RangeList()
    {
        rangeList = new LinkedList<IPv4Range>();
    }

    //NOTE: Must be read-only so we don't return a read-only copy of the list
    //  while modifications are being made.
    public synchronized List getRangeList()
    {
        return Collections.unmodifiableList(rangeList);
    }

    public synchronized void addRange(IPv4Range _newRange)
    {
        ListIterator<IPv4Range> iter = rangeList.listIterator();

        IPv4Range currRange;
        IPv4Range mergedNewRange = _newRange;
        while (iter.hasNext())
        {
            currRange = iter.next();

            if (currRange.overlapsWithRange(_newRange))
            {
                mergedNewRange = currRange.rangeUnion(mergedNewRange);
                iter.remove();
            }
        }

        iter = rangeList.listIterator();
        IPv4Range prevRange = null;
        currRange = null;
        while (iter.hasNext())
        {
            prevRange = currRange;
            currRange = iter.next();

            if (IPv4Range.compareAddresses(mergedNewRange.getEndAddr(),
                    currRange.getStartAddr()) == ComparisonResult.BEFORE
                    && (prevRange == null || IPv4Range.compareAddresses(
                    prevRange.getEndAddr(), mergedNewRange.getStartAddr())
                    == ComparisonResult.AFTER))
            {
                iter.previous();
                iter.add(mergedNewRange);
                return;
            }
        }
        
        iter.add(mergedNewRange);
    }

    private List<IPv4Range> rangeList;
}
